<?php
/**
 * GioCMS
 * 
 * LICENSE
 *
 * This source file is subject to the GNU GENERAL PUBLIC LICENSE Version 2 
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-2.0.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@ninhgio.com so we can send you a copy immediately.
 * 
 * @copyright	Copyright (c) 2010-2011 GioCMS (http://cms.ninhgio.com)
 * @license		http://www.gnu.org/licenses/gpl-2.0.txt GNU GENERAL PUBLIC LICENSE Version 2
 * @author		NinhGio - ninhgio@gmail.com
 * @since		1.0
 */

class Gio_Core_Session
{
	public function __construct()
	{
		@session_start();
	}
	
	public static function set($name, $value = null, $sessionId = null)
	{
		$session = self::getSessionById($sessionId);
		if ($session != null) {
			$json = new Services_JSON();
			$data = $json->encodeUnsafe($value);
			self::update($data, $sessionId);
		}
		return null;
	}
	
	public static function get($name, $sessionId = null)
	{
		$session = self::getSessionById($sessionId);
		if (null == $session) {
			return null;
		}
		
		return (isset($session[$name])) ? $session[$name] : null;
	}
	
	public static function exist($name = null, $sessionId = null)
	{
		$session = self::getSessionById($sessionId);
		if ($session != null) {
			if (!$name) {
				return true;
			}
			$json = new Services_JSON();
			$data = $session['data'];	
			return (isset($data[$name])) ? true : false;
		}
		return null;
	} 
	
	public static function remove($name)
	{
		$name = self::getName($name);
		unset($_SESSION[$name]);
	}
	
	public static function destroy($sessionId = null)
	{
		$sessionId = ($sessionId) ? $sessionId : self::getId();
		/**
		 * 
		 */
		$mysql = new Gio_Db_Mysql();
		$sql = 'DELETE FROM ' . $mysql->_tablePrefix . 'core_session 
						WHERE session_id = "' . $mysql->escape($sessionId) . '"';
		$rs = $mysql->query($sql);
		$mysql->freeResult($rs);
		return $mysql->affectedRows();
	}
	
	public static function getId()
	{
		return session_id();
	}
	
	/**
	 * 
	 * @param $data
	 */
	public static function add($session) 
	{
		if (self::getSessionById($session['session_id'], $session) != null) {
			return;
		}
		$mysql = new Gio_Db_Mysql();
		return $mysql->insert($session, $mysql->_tablePrefix . 'core_session');
	}
	
	public static function update($data, $sessionId = null)
	{
		$mysql = new Gio_Db_Mysql();
		$request = Gio_Core_Request::getInstance();
		
		$sessionId = ($sessionId != null) ? $sessionId : self::getId();
		$sql = 'UPDATE ' . $mysql->_tablePrefix . 'core_session 
					SET data = "%s", ip = "%s" 
					WHERE session_id = "%s"';
		$sql = sprintf($sql, $mysql->escape($data),
							 $mysql->escape($request->getRemoteIp()),
							$mysql->escape($sessionId));
		$rs = $mysql->query($sql);
		/**
		 * Free result 
		 */
		$mysql->freeResult($rs);
		return $mysql->affectedRows();
	}
	
	public static function lastUpdate($time, $sessionId = null)
	{
		$mysql = new Gio_Db_Mysql();
		$request = new Gio_Core_Request();
		$sessionId = ($sessionId != null) ? $sessionId : self::getId();
		$sql = 'UPDATE ' . $mysql->_tablePrefix . 'core_session 
					SET last_update = "%s", status = "active", ip = "%s" 
					WHERE session_id = "%s"';
		$sql = sprintf($sql, $mysql->escape($time),
							$mysql->escape($request->getRemoteIp()),
							$mysql->escape($sessionId));
		$rs = $mysql->query($sql);
		/**
		 * Free result 
		 */
		$mysql->freeResult($rs);
		return $mysql->affectedRows();
	}
	
	public static function getSessionById($sessionId = null, $session = null)
	{
		$configs = Gio_Core_Config_Xml::getConfig('session');
		
		$sessionId = ($sessionId) ? $sessionId : self::getId();
		$mysql = new Gio_Db_Mysql();
		/**
		 * Clear Session Expried
		 */
		$sql = 'DELETE FROM ' . $mysql->_tablePrefix . 'core_session
					WHERE last_update + lifetime < ' . strtotime(date('Y-m-d H:i:s')); 
		$rs = $mysql->query($sql);
		$mysql->freeResult($rs);
		
		/**
		 * Update Session Status
		 */
		$sql = 'UPDATE ' . $mysql->_tablePrefix . 'core_session
				SET status = "inactive"
				WHERE last_update + inactive_time < ' . strtotime(date('Y-m-d H:i:s')); 
		$rs = $mysql->query($sql);
		$mysql->freeResult($rs);
		
		/**
		 * 
		 */
		$sql = 'SELECT * FROM ' . $mysql->_tablePrefix . 'core_session 
						WHERE session_id = "' . $mysql->escape($sessionId) . '" LIMIT 1';
		$rs = $mysql->query($sql);
		$row = (0 == $mysql->count($rs)) ? null : $mysql->fetchAll($rs);
		$json = new Services_JSON();
		
		if (null == $row) {
			$request = Gio_Core_Request::getInstance();
			$session = array(
				'session_id'	=> $sessionId,
				'data'			=> null,
				'created_date'	=> time(),
				'last_update'	=> time(),
				'lifetime'		=> (isset($configs->lifetime))
										? $configs->lifetime : 3600,
				'inactive_time'	=> (isset($configs->inactive))
										? $configs->inactive : 120,
				'ip'			=> $request->getRemoteIp(),
				
			);
			$mysql->insert($session, $mysql->_tablePrefix . 'core_session');
			return $session;
		}
		
		self::lastUpdate(time(), $row['session_id']);
		if ($session != null) {
			self::update($session['data'], $session['session_id']);
			return $session;
		}
		return $row;
	}
	
	public static function getUser()
	{
		$session = self::getSessionById();
		
		$json = new Services_JSON();
		$user = (null == $session || null == $session['data']) 
										? null : $json->decode($session['data']);
		return (array)$user;
	}
	
	public static function countOnline($login = false)
	{
		$mysql = new Gio_Db_Mysql();
		$sql = 'SELECT COUNT(*) as num_online FROM ' . $mysql->_tablePrefix .'core_session
				WHERE status = "active"';
		if ($login) {
			$sql .= ' AND data != ""';
		}
		$rs = $mysql->query($sql);
		$row = $mysql->fetchAll($rs);
		$mysql->freeResult($rs);
		
		$number = $row['num_online'];
		return $number;
	}
	
	public static function getUsersOnline()
	{
		$mysql = new Gio_Db_Mysql();
		$sql = 'SELECT * FROM ' . $mysql->_tablePrefix .'core_session AS s
				WHERE status = "active" AND data != ""';
		
		$rs = $mysql->query($sql);
		$sessions = array();
		while ($row = $mysql->fetchAll($rs)) {
			$sessions[] = $row;
		}
		/**
		 * Free result 
		 */
		$mysql->freeResult($rs);
		return $sessions;
	}
}